% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Replication "Deconstructing the Yield Curve"
% Crump and Gospodinov (2024)
% Date: 26-JUL-2024
% Function for calculating principal components w/ ordered output
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [loadings,eigenvalues] = OrderedPCA(y,matType)
% OrderedPCA This function calculates principal component loadings and
%           associated eigenvalues ordered from larges to smallest
% INPUTS   
%           y          Data matrix (TxN with T  N) or covariance matrix
%           matType    If using a data matrix, then specify whether you would like data to 
%                         be standardized ('corr') or not ('cov'); 
%                      omit if input is a symmetric, square matrix.

    N = size(y,2);
    
    if nargin == 1
        [tmpLoadings,tmpEigenvalues] = eig(y, 'vector');
    elseif nargin == 2
        if strcmp(matType, 'cov')
            [tmpLoadings, ~, tmpEigenvalues] = pca(y);
        elseif strcmp(matType, 'corr')
            [tmpLoadings, ~, tmpEigenvalues] = pca(zscore(y));
        end        
    end
    
    [~,idx] = sort(tmpEigenvalues,'descend');
    
    eigenvalues = tmpEigenvalues(idx);
    loadings = tmpLoadings(:,idx);
    loadings = loadings.*repmat(sign(loadings(1,:)),[N,1]);
   
end

